﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using OpenTK;
using Utils;
using OpenTK.Graphics.OpenGL;

namespace Camera
{
    /// <summary>
    /// Camera class that will hold the translation matrix for a particular viewing angle  
    /// 
    /// The class assumes that forward is in the Z axis, right strafe is the positive X axis,
    /// and up is the positive Y axis
    /// </summary>
    [Serializable]
    public class CameraObject
    {
        /// <summary>
        /// Gets or sets the angle at which the camera is facing (left/right)
        /// </summary>
        /// <value>
        /// The angle.
        /// </value>
        public Angle3D Angle;

        /// <summary>
        /// Gets or sets the azimuth (up/down)
        /// </summary>
        /// <value>
        /// The azimuth.
        /// </value>
        public Angle3D Azimuth;

        /// <summary>
        /// Gets or sets the position of the camera.
        /// </summary>
        /// <value>
        /// The position.
        /// </value>
        public Point3D Position;

        /// <summary>
        /// Gets or sets the object GUID.
        /// </summary>
        /// <value>
        /// The object GUID.
        /// </value>
        public Guid ObjectGuid;

        public BoundingBox Box { get { return new BoundingBox(Position, 2, 2, 2); } }

        [NonSerialized]
        private MeshData _model;

        public CameraObject()
        {
            Angle = new Angle3D();
            Azimuth = new Angle3D { AngleDegrees = 90 };
            Position = new Point3D(0, 0, 3);
            ObjectGuid = Guid.NewGuid();
        }

        public void TranslateLocal(Point3D localTranslation)
        {
            double x = Angle.CosAngle * localTranslation.X + Angle.SinAngle * localTranslation.Z;
            double y = localTranslation.Y;
            double z = -Angle.SinAngle * localTranslation.X + Angle.CosAngle * localTranslation.Z;
            
            

            Position.Z += z;
            Position.X += x;
            Position.Y += y;
            if (Position.Y > 0.1)
            {
                SoundUtils.PlayTestPostion();
            }
            SoundUtils.PlayFootStep();
        }

        public void RotateAngleLocal(Angle3D angle)
        {
            if (angle.AngleRadians != 0)
                Angle.AngleRadians += angle.AngleRadians;
        }

        public void RotateAzimuthLocal(Angle3D angle)
        {
            if (angle.AngleRadians != 0 && Azimuth.AngleDegrees + angle.AngleDegrees < 175 && Azimuth.AngleDegrees + angle.AngleDegrees > 5)
                Azimuth.AngleRadians += angle.AngleRadians;
        }

        public Matrix4d GetCameraMatrix()
        {
            var eye = new Vector3d(Position.X, Position.Y, Position.Z);
            var target = new Vector3d(Position.X, Position.Y, Position.Z);

            target.Z -= Angle.CosAngle * Azimuth.SinAngle;
            target.X -= Angle.SinAngle * Azimuth.SinAngle;

            target.Y -= Azimuth.CosAngle;

            return Matrix4d.LookAt(eye, target, Vector3d.UnitY);
        }

        public void DrawCamera()
        {
            if (_model == null)
                _model = ObjLoader.LoadStream("camera.obj");
            _model.Offset = new Point3D(Position.X, Position.Y + 5, Position.Z);
            //model.Offset.Y += 5;
            _model.DrawMesh();

            //GL.Begin(BeginMode.Points);
            //GL.Vertex3(Position.Z,Position.Y,Position.Z);
            //GL.End();
        }

        public void Update(CameraObject camera)
        {
            Position = camera.Position;
            Angle = camera.Angle;
            Azimuth = camera.Azimuth;
        }
    }
}
